package com.xhwl.centiotdata.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhwl.centiotdata.dao.RepairOperateLogMapper;
import com.xhwl.centiotdata.service.RepairDetailLogService;
import com.xhwl.centiotdata.service.RepairOperateLogService;
import com.xhwl.common.dto.cent.iotdata.repair.RepairActionDTO;
import com.xhwl.common.enums.iot.RepairResultEnum;
import com.xhwl.common.enums.iot.RepairStepResultEnum;
import com.xhwl.common.pojo.cent.iot.RepairDetailLog;
import com.xhwl.common.pojo.cent.iot.RepairOperateLog;
import com.xhwl.common.pojo.cent.sdata.Account;
import com.xhwl.common.query.cent.iotdata.RepairLogQuery;
import com.xhwl.common.utils.CalendarUtil;
import com.xhwl.common.utils.DataVerifyUtil;
import com.xhwl.common.utils.StringUtils;
import com.xhwl.common.vo.cent.iot.PageSimpleVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 数据补救操作日志
 */
@Service
public class RepairOperateLogServiceImpl extends ServiceImpl<RepairOperateLogMapper, RepairOperateLog>
        implements RepairOperateLogService {

    RepairDetailLogService repairDetailLogService;

    @Autowired
    public void setRepairDetailLogService(RepairDetailLogService repairDetailLogService) {
        this.repairDetailLogService = repairDetailLogService;
    }

    @Override
    public PageSimpleVO<RepairOperateLog> operateLogQuery(RepairLogQuery repairLogQuery) {
        String nameOrPhone = repairLogQuery.getNameOrPhone();
        Page<RepairOperateLog> result = getBaseMapper().selectPage(new Page<>(repairLogQuery.getPageNum(), repairLogQuery.getPageSize()), new LambdaQueryWrapper<RepairOperateLog>()
                .eq(RepairOperateLog::getProjectId, repairLogQuery.getProjectId())
                .and(StringUtils.isNotEmpty(nameOrPhone),
                        wrapper -> wrapper.like(DataVerifyUtil.isNumber(nameOrPhone), RepairOperateLog::getOperatorPhone, nameOrPhone)
                                .or()
                                .like(RepairOperateLog::getOperatorName, nameOrPhone)
                )
                .ge(isCorrectDate(repairLogQuery.getStartDate()), RepairOperateLog::getOperateDate, transformDate(repairLogQuery.getStartDate()))
                .le(isCorrectDate(repairLogQuery.getEndDate()), RepairOperateLog::getOperateDate, transformDate(repairLogQuery.getEndDate() + " 23:59:59"))
                .orderByDesc(RepairOperateLog::getOperateDate)
        );
        return PageSimpleVO.transform(result);
    }

    @Override
    public RepairOperateLog initOperate(RepairActionDTO repairActionDTO, Account account) {
        RepairOperateLog repairOperateLog = new RepairOperateLog();
        repairOperateLog.setProjectId(repairActionDTO.getProjectId());
        repairOperateLog.setOperateType(repairActionDTO.getOperateType());
        Date start = transformDate(repairActionDTO.getStartDate());
        Date end = transformDate(repairActionDTO.getEndDate());
        if (start == null || end == null)
            return null;
        repairOperateLog.setDateStart(start);
        repairOperateLog.setDateEnd(end);
        repairOperateLog.setOperateDate(new Date());
        if (account != null && account.getId() != null) {
            repairOperateLog.setOperatorId(account.getId().toString());
            repairOperateLog.setOperatorName(account.getName());
            repairOperateLog.setOperatorPhone(account.getPhone());
        }
        repairOperateLog.setOperateResult(RepairResultEnum.INVOKING.getType());
        if (getBaseMapper().insert(repairOperateLog) > 0) {
            return repairOperateLog;
        } else {
            return null;
        }
    }

    @Override
    public boolean isRepairInvoking(RepairActionDTO repairActionDTO) {
        List<RepairOperateLog> repairOperateLogs = getBaseMapper().selectList(new LambdaQueryWrapper<RepairOperateLog>().eq(RepairOperateLog::getProjectId, repairActionDTO.getProjectId())
                .eq(RepairOperateLog::getOperateResult, RepairResultEnum.INVOKING));
        return !CollectionUtils.isEmpty(repairOperateLogs);
    }

    @Override
    public void updateOperateResult(RepairResultEnum repairResultEnum, Integer taskId) {
        RepairOperateLog repairOperateLog = new RepairOperateLog();
        repairOperateLog.setId(taskId);
        repairOperateLog.setOperateResult(repairResultEnum.getType());
        updateById(repairOperateLog);
    }

    @Override
    public void delayCheckTimeOut(long second, Integer taskId) {
        if (taskId == null)
            return;
        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.schedule(() -> checkTimeOut(taskId), second, TimeUnit.SECONDS);
    }


    private void checkTimeOut(Integer taskId) {
        RepairOperateLog one = getById(taskId);
        if (one == null) {
            return;
        }
        RepairResultEnum last = RepairResultEnum.getEnum(one.getOperateResult());
        //代表超时，从detail中收集结果，修改状态
        if (last == null || last == RepairResultEnum.INVOKING) {
            RepairResultEnum result;
            List<RepairDetailLog> operateDetail = repairDetailLogService.getOperateDetail(taskId);
            if (CollectionUtils.isEmpty(operateDetail)) {
                result = RepairResultEnum.SUCCESS;
            } else {
                List<Integer> collect = operateDetail.stream().map(repairDetailLog -> repairDetailLog.getOperateResult()).collect(Collectors.toList());
                if (collect.contains(RepairStepResultEnum.SUCCESS)) {
                    result = collect.contains(RepairStepResultEnum.FAILED) ? RepairResultEnum.LOST : RepairResultEnum.SUCCESS;
                } else {
                    result = RepairResultEnum.FAILED;
                }
            }
            updateOperateResult(result, taskId);
        }
    }

    private Date transformDate(String dateStr) {
        //可能带入null字符串的组合进来，筛选下
        if (StringUtils.isEmpty(dateStr) || dateStr.startsWith("null"))
            return null;
        //补全时间
        if (dateStr.length() == CalendarUtil.DATE_FORMAT[1].length()) {
            dateStr += " 00:00:00";
        }
        try {
            Date date = CalendarUtil.getDate(CalendarUtil.DATE_FORMAT[0], dateStr);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 是否是正确的日期, yyyy-MM-dd
     *
     * @param date
     * @return
     */
    private boolean isCorrectDate(String date) {
        return CalendarUtil.isAccurateDate(date, RepairActionDTO.getDefaultDatePattern());
    }
}




